#include "volumeactivation.h"

//静态变量初始化
int VolumeActivation::activate_ret = 1;
int VolumeActivation::recycle_ret =1;
QString VolumeActivation::act_code;
QString VolumeActivation::ser_num_by_server;
QString VolumeActivation::topic_activate;
QString VolumeActivation::topic_recycle;
QString VolumeActivation::topic_status_response;
QString VolumeActivation::_sn;
QMap<QString,QString> VolumeActivation::map;
bool VolumeActivation::is_subscribe_register = false;

VolumeActivation::VolumeActivation(QObject *parent)
    : QObject(parent)
{
    dbus_init();

    this->timer = new QTimer(this);
    this->connect_num = 0;
    //libmosquitto 库初始化
    mosquitto_lib_init();
    //创建mosquitto客户端
    mosq = mosquitto_new(NULL,true,NULL);
    if(!mosq){
        qDebug()<<"create client failed..";
        mosquitto_lib_cleanup();
    }

    mosquitto_connect_callback_set(mosq, myConnectCallback);
    mosquitto_message_callback_set(mosq, myMessageCallback);
    mosquitto_publish_callback_set(mosq, myPublishCallback);

    connect(this->timer, SIGNAL(timeout()), this, SLOT(mqttConnect()));
}

VolumeActivation::~VolumeActivation()
{
    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();
}

void VolumeActivation::myPublishCallback(mosquitto *mosq, void *obj, int mid)
{
    qDebug()<<"发布消息成功！";
}

void VolumeActivation::myMessageCallback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
{
    qDebug()<<"topic_status_response: "<<topic_status_response.toLocal8Bit().data();
    qDebug()<<"topic_activate: "<<topic_activate.toLocal8Bit().data();
    qDebug()<<"topic_recycle: "<<topic_recycle.toLocal8Bit().data();
    if(strcmp(message->topic,"kylin/register/response") == 0) { //接收到注册回复消息
        char *ch = (char *)message->payload;
        qDebug()<<"接收到注册回复消息："<<message->topic<<ch;

        QString str = QString::fromLocal8Bit(ch);
        QJsonDocument jsonDocument = QJsonDocument::fromJson(str.toLocal8Bit().data());
        if(jsonDocument.isNull()) {
            qDebug()<< "接收到注册回复消息为空:"<< str.toLocal8Bit().data();
            QThread::sleep(60);
            mqttPublish(mosq, "kylin/register/request");
        } else {
            //version:版本号，ser_num:服务序列号，hd_code:硬件编码，ret:0成功/非0失败
            QJsonObject jsonObject = jsonDocument.object();
            if(jsonObject.contains("ser_num")) {
                QJsonValue ser_num_value = jsonObject.take("ser_num");
                if(ser_num_value.isString()) {
                    ser_num_by_server = ser_num_value.toString();
                }
            }
            int ret=-1;
            if(jsonObject.contains("ret")) {
                QJsonValue ret_value = jsonObject.take("ret");
                if(ret_value.isDouble()) {
                    ret = ret_value.toVariant().toInt();
                }
            }
            if(ret == 0) {
                qDebug()<<"is_subscribe_register:"<<is_subscribe_register;
                if(!is_subscribe_register) {
                    QByteArray ba = ser_num_by_server.toLatin1();
                    gchar *input_serial = ba.data();
                    _sn = new_register_number(input_serial)->at(0);
                    topic_activate = QString("kylin/activate/request/%1").arg(_sn);
                    topic_recycle = QString("kylin/recycle/request/%1").arg(_sn);
                    topic_status_response = QString("kylin/status/response/%1").arg(_sn);
                    qDebug()<<"订阅批量激活、批量取消与状态上报主题："<<topic_activate<<topic_recycle<<topic_status_response;
                    mosquitto_subscribe(mosq, NULL, topic_activate.toLocal8Bit().data(), 2);
                    mosquitto_subscribe(mosq, NULL, topic_recycle.toLocal8Bit().data(), 2);
                    mosquitto_subscribe(mosq, NULL, topic_status_response.toLocal8Bit().data(), 2);
                    //上报激活状态
                    mqttPublish(mosq, "kylin/status/request");
                    is_subscribe_register=!is_subscribe_register;
                }
            } else {
                QThread::sleep(60);
                qDebug()<<"Re-submit activation status.";
                mqttPublish(mosq, "kylin/register/request");
            }
        }
    } else if(strcmp(message->topic, topic_status_response.toLocal8Bit().data()) == 0) { //接收到上报状态回复消息
        char *ch = (char *)message->payload;
        qDebug()<<"接收到上报状态回复消息："<<message->topic<<ch;

        QString str = QString::fromLocal8Bit(ch);
        QJsonDocument jsonDocument = QJsonDocument::fromJson(str.toLocal8Bit().data());
        if(jsonDocument.isNull()) {
            qDebug()<< "接收到上报状态回复消息为空："<< str.toLocal8Bit().data();
        } else {
            QJsonObject jsonObject = jsonDocument.object();
            //version:版本号，ret:0成功/非0失败
            if(jsonObject.contains("version")) {
                QJsonValue version_value = jsonObject.take("version");
                if(version_value.isString()) {
                    QString version = version_value.toString();
                }
            }
            if(jsonObject.contains("ret")) {
                QJsonValue ret_value = jsonObject.take("ret");
                if(ret_value.isDouble()) {
                    int ret = ret_value.toVariant().toInt();
                }
            }
        }
    } else if(strcmp(message->topic, topic_activate.toLocal8Bit().data()) == 0) { //接收到批量激活消息
        char *ch = (char *)message->payload;
        qDebug()<<"接收到批量激活消息："<<message->topic<<ch;

        QString str = QString::fromLocal8Bit(ch);
        QJsonDocument jsonDocument = QJsonDocument::fromJson(str.toLocal8Bit().data());
        if(jsonDocument.isNull()) {
            qDebug()<< "接收到批量激活消息为空："<< str.toLocal8Bit().data();
        } else {
            QJsonObject jsonObject = jsonDocument.object();
            QString version, customer;
            //version:版本号，act_code:激活码，customer:用户单位
            if(jsonObject.contains("version")) {
                QJsonValue version_value = jsonObject.take("version");
                if(version_value.isString()) {
                    version = version_value.toString();
                }
            }
            if(jsonObject.contains("act_code")) {
                QJsonValue act_code_value = jsonObject.take("act_code");
                if(act_code_value.isString()) {
                    act_code = act_code_value.toString();
                }
            }
            if(jsonObject.contains("customer")) {
                QJsonValue customer_value = jsonObject.take("customer");
                if(customer_value.isString()) {
                    customer = customer_value.toString();
                }
            }

            //激活操作
            set_customer(customer.toLatin1().data());
            activate_ret = new_active_code(ser_num_by_server.toLatin1().data(), act_code.toLatin1().data());

            mqttPublish(mosq, "kylin/activate/response");//激活操作完成后向服务端回消息
        }
    } else if(strcmp(message->topic, topic_recycle.toLocal8Bit().data()) == 0) {//接收到批量取消消息
        char *ch = (char *)message->payload;
        qDebug()<<"接收到批量取消消息："<<message->topic<<ch;

        QString str = QString::fromLocal8Bit(ch);
        QJsonDocument jsonDocument = QJsonDocument::fromJson(str.toLocal8Bit().data());
        if(jsonDocument.isNull()) {
            qDebug()<< "接收到批量取消消息为空:"<< str.toLocal8Bit().data();
        } else {
            QJsonObject jsonObject = jsonDocument.object();
            //version:版本号，act_code:激活码
            if(jsonObject.contains("version")) {
                QJsonValue version_value = jsonObject.take("version");
                if(version_value.isString()) {
                    QString version = version_value.toString();
                }
            }
            if(jsonObject.contains("act_code")) {
                QJsonValue act_code_value = jsonObject.take("act_code");
                if(act_code_value.isString()) {
                    act_code = act_code_value.toString();
                }
            }

            //取消激活
            bool recycle_result = remove_activation_file();
            if(recycle_result) {
                recycle_ret = 0;
            } else {
                recycle_ret = 1;
            }
            mqttPublish(mosq, "kylin/recycle/response");
        }
    } else {
        char *ch = (char *)message->payload;
        qDebug()<<"-------："<<message->topic<<ch;
        qDebug()<<"未匹配到订阅的主题！"<<message->topic;
    }
}

void VolumeActivation::myConnectCallback(struct mosquitto *mosq, void *userdata, int result)
{
    if(!result){
        /* Subscribe to broker information topics on successful connect. */
        mqttPublish(mosq, "kylin/register/request");

    }else{
        qDebug()<<"Connect failed!";
    }
}

void VolumeActivation::mqttConnect()
{
    connect_num += 1;
    qDebug()<<"尝试连接"<<connect_num<<"次";
    if(connect_num > 15)
    {
        this->timer->stop();
        exit_service();
        qApp->exit(0);
    }

    //客户端连接服务器byte_arrt.data()->172.20.12.207
    if(mosquitto_connect(mosq, server_dns.toLocal8Bit().data(), PORT, 60)){
        qDebug()<<"Unable to connect!";
    } else {
        mqttSubscription("kylin/register/response");
        mosquitto_loop_forever(mosq, -1, 1);
        this->timer->stop();

        QDBusConnection::systemBus().connect("org.freedesktop.activation",
                                             "/org/freedesktop/activation",
                                             "org.freedesktop.activation.interface",
                                             "activation_result",
                                             this,
                                             SLOT(sendActivationStateSlot()));
    }
}

void VolumeActivation::sendActivationStateSlot()
{
    qDebug()<<"更新上报激活状态！";
    //上报激活状态
    mqttPublish(mosq, "kylin/status/request");
}

void VolumeActivation::mqttPublish(struct mosquitto *mosq, char *topic)
{
    QString version = "02-02";//版本号
    QString ser_num = get_serial_number();//服务序列号kyinfo 字段
    QString SN;//8位显示注册码，7位显示null
    if(ser_num.length() != 7)
    {
        QByteArray ba = ser_num.toLatin1();
        gchar *input_serial = ba.data();
        SN = new_register_number(input_serial)->at(0);
    }
    QString hd_code = get_harddisk_id();//绑定的硬件信息，不base64
    if(hd_code == nullptr) {
        hd_code = get_interface_mac();
    }

    if(hd_code.isEmpty()||hd_code==""||hd_code==nullptr) {
        qWarning()<<"Can't get hd_code, exit.";
        exit(0);
    }

    QJsonArray mac;//["网卡1mac"，"网卡2mac"，"网卡3mac"]
    foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces()) {
        if (!(interface.flags() & QNetworkInterface::IsLoopBack) && interface.isValid())
            mac.append(interface.hardwareAddress());
    }
    QJsonArray ip;//["172.30.10.8"]
    foreach(const QHostAddress& hostAddress,QNetworkInterface::allAddresses())
    {
        if(hostAddress.toIPv4Address() && hostAddress != QHostAddress::LocalHost)
        {
            ip.append(hostAddress.toString());
        }
    }
    QString hostname = QHostInfo::localHostName();//主机名
    QString host_ser_num = get_service_tag();//主机序列号

    if(strcmp(topic, "kylin/register/request") == 0)//发布注册消息
    {
        //生成json数据
        QJsonObject jsonObject;
        jsonObject.insert("version", version);
        jsonObject.insert("SN", SN);
        jsonObject.insert("ser_num", ser_num);
        jsonObject.insert("hd_code", hd_code);
        jsonObject.insert("mac", mac);
        jsonObject.insert("host_ser_num", host_ser_num);
        jsonObject.insert("ip", ip);
        jsonObject.insert("hostname", hostname);

        QMap<QString,QString>::iterator it=map.begin();
        while(it!=map.end())
        {
            jsonObject.insert(it.key(),it.value());
            it++;
        }

        //json转化为qbytearry转化为char
        QJsonDocument document;
        document.setObject(jsonObject);
        QByteArray byte_array = document.toJson(QJsonDocument::Compact);

        qDebug()<<"发布注册消息："<<byte_array.data();

        //发布注册信息
        mosquitto_publish(mosq, NULL, "kylin/register/request", strlen(byte_array.data()), byte_array.data(), 2, 0);

    }
    else if(strcmp(topic, "kylin/status/request") == 0)//发布激活状态消息
    {
        QString activate_status;
        QString activate_state_date = NULL;

        if(status_code() == 0) {
            activate_state_date = status_date();
            if(activate_state_date != "" ) { //激活过期
                activate_status = "activated";
            } else {
                activate_status = "not_activated";
            }
        } else if(status_code() == 1) {
            activate_status = "activated";
        }

        //生成json数据
        QJsonObject jsonObject;
        jsonObject.insert("version", version);
        jsonObject.insert("SN", SN);
        jsonObject.insert("ser_num", ser_num);
        jsonObject.insert("hd_code", hd_code);
        jsonObject.insert("mac", mac);
        jsonObject.insert("ip", ip);
        jsonObject.insert("hostname", hostname);
        jsonObject.insert("host_ser_num", host_ser_num);
        jsonObject.insert("activate_status", activate_status);

        QMap<QString,QString>::iterator it=map.begin();
        while(it!=map.end())
        {
            jsonObject.insert(it.key(),it.value());
            it++;
        }

         //json转化为qbytearry转化为char
        QJsonDocument document;
        document.setObject(jsonObject);
        QByteArray byte_array = document.toJson(QJsonDocument::Compact);

        qDebug()<<"发布激活状态消息："<<byte_array.data();

        //发布激活状态消息
        mosquitto_publish(mosq, NULL, "kylin/status/request", strlen(byte_array.data()), byte_array.data(), 0, 0);
    }
    else if(strcmp(topic, "kylin/activate/response") == 0)//发布激活结果消息
    {
        //生成json数据
        QJsonObject jsonObject;
        jsonObject.insert("version", version);
        jsonObject.insert("SN", _sn);
        jsonObject.insert("ret", activate_ret);

         //json转化为qbytearry转化为chars
        QJsonDocument document;
        document.setObject(jsonObject);
        QByteArray byte_array = document.toJson(QJsonDocument::Compact);

        qDebug()<<"发布激活结果消息："<<byte_array.data();

        //发布激活结果消息
        mosquitto_publish(mosq, NULL, "kylin/activate/response", strlen(byte_array.data()), byte_array.data(), 0, 0);
    }
    else if(strcmp(topic, "kylin/recycle/response") == 0)//发布回收结果消息
    {
        //生成json数据
        QJsonObject jsonObject;
        jsonObject.insert("version", version);
        jsonObject.insert("SN", _sn);
        jsonObject.insert("ret",recycle_ret);

        //json转化为qbytearry转化为char
        QJsonDocument document;
        document.setObject(jsonObject);
        QByteArray byte_array = document.toJson(QJsonDocument::Compact);

        qDebug()<<"发布回收结果消息："<<byte_array.data();

        //发布回收结果消息
        mosquitto_publish(mosq, NULL, "kylin/recycle/response", strlen(byte_array.data()), byte_array.data(), 0, 0);
        if(recycle_ret == 0)
            exit_service();
    }
    else
    {
        qDebug()<<"未匹配到发布的主题！"<<topic;
    }
}

void VolumeActivation::mqttSubscription(char *topic)
{
    qDebug()<<"订阅注册回复消息！";
    mosquitto_subscribe(mosq, NULL, topic, 2);
}

void VolumeActivation::searchServerIp()
{
    //查找需要发送的消息
    QSettings settingsMesg("/usr/share/kylin-activation/message_sent_conf.ini", QSettings::IniFormat);
    settingsMesg.beginGroup("Message_Sent");
    QStringList keys= settingsMesg.childKeys();
    Q_FOREACH(QString key, keys)
    {
        QString val=settingsMesg.value(key).toString();
        if(!val.isEmpty())
        {
            map.insert(QString(key.toLatin1()),QString(val.toLatin1()));
        }
    }
    settingsMesg.endGroup();
    qDebug()<<"自定义消息:"<<map;

    //查找服务端ip
    this->server_dns.clear();
    QSettings settings("/etc/kylin-activation/activation_conf.ini", QSettings::IniFormat);
    this->server_dns = settings.value("KMS_Activation/ServerIp").toString();
    if (this->server_dns.isEmpty()) {
        QString config_path = QDir::homePath() + "/.config/activation_conf.ini";
        QSettings settings(config_path, QSettings::IniFormat);
        this->server_dns = settings.value("KMS_Activation/hostaddr").toString();
        if (this->server_dns == "")
            qDebug()<<"Can't get server address.";
    }
    qDebug()<<"server_dns: " <<this->server_dns;
    QHostInfo::lookupHost(this->server_dns,this, [=](QHostInfo host)
    {
        if(host.error()!=QHostInfo::NoError)
        {
            qDebug() << "Lookup failed:" << host.errorString();
            this->timer->start(4000);
            return;
        }

        Q_FOREACH(QHostAddress address, host.addresses())
        {
            qDebug() << "Found address:" << address.toString();
            this->server_dns.clear();
            this->server_dns=address.toString();
            this->timer->start(4000);
            break;
        }
    });
}
